{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "471686fe-a398-4268-8360-ed1b30f4884f",
   "metadata": {},
   "source": [
    "## OpenAI \n",
    "\n",
    "For this notebook we will use the OpenAI ChatGPT models. We import the OpenAI agent and set the api_key, you will have to provide your own API key. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56f0ce8c-c65c-4b6b-932f-d88620d402de",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Setup OpenAI Agent\n",
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"sk-your-key\"\n",
    "\n",
    "from llama_index.core.agent.workflow import FunctionAgent\n",
    "from llama_index.llms.openai import OpenAI"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9515f57c-408b-4ec2-97ba-048e5f89b7d2",
   "metadata": {},
   "source": [
    "## Database tool\n",
    "\n",
    "This tool connects to a database (using SQLAlchemy under the hood) and allows an Agent to query the database and get information about the tables.\n",
    "\n",
    "We import the ToolSpec and initialize it so that it can connect to our database"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cdc11ff-4cde-44ed-a2a3-5509d1582a11",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import and initialize our tool spec\n",
    "from llama_index.tools.database.base import DatabaseToolSpec\n",
    "\n",
    "db_spec = DatabaseToolSpec(\n",
    "    scheme=\"postgresql\",  # Database Scheme\n",
    "    host=\"localhost\",  # Database Host\n",
    "    port=\"5432\",  # Database Port\n",
    "    user=\"postgres\",  # Database User\n",
    "    password=\"x\",  # Database Password\n",
    "    dbname=\"your_db\",  # Database Name\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "886a9be7-9048-43ac-86f0-7a69ed6ad408",
   "metadata": {},
   "source": [
    "After initializing the Tool Spec we have an instance of the ToolSpec. A ToolSpec can have many tools that it implements and makes available to agents. We can see the Tools by converting to the spec to a list of FunctionTools, using `to_tool_list`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b370966-379a-4025-b201-855c115cc2e0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load_data\n",
      "load_data(query: str) -> List[llama_index.schema.Document]\n",
      "Query and load data from the Database, returning a list of Documents.\n",
      "\n",
      "        Args:\n",
      "            query (str): an SQL query to filter tables and rows.\n",
      "\n",
      "        Returns:\n",
      "            List[Document]: A list of Document objects.\n",
      "        \n",
      "<class 'pydantic.main.load_data'>\n",
      "describe_tables\n",
      "describe_tables(tables: Optional[List[str]] = None) -> str\n",
      "\n",
      "            Describes the specifed tables in the database\n",
      "\n",
      "            Args:\n",
      "                tables (List[str]): A list of table names to retrieve details about\n",
      "        \n",
      "<class 'pydantic.main.describe_tables'>\n",
      "list_tables\n",
      "list_tables() -> List[str]\n",
      "\n",
      "            Returns a list of available tables in the database.\n",
      "            To retrieve details about the columns of specfic tables, use\n",
      "            the describe_tables endpoint\n",
      "        \n",
      "<class 'pydantic.main.list_tables'>\n"
     ]
    }
   ],
   "source": [
    "tools = db_spec.to_tool_list()\n",
    "for tool in tools:\n",
    "    print(tool.metadata.name)\n",
    "    print(tool.metadata.description)\n",
    "    print(tool.metadata.fn_schema)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "695a9655-d66e-4c4e-b660-b8a59e9ba5c8",
   "metadata": {},
   "source": [
    "We can see that the database tool spec provides 3 functions for the OpenAI agent. One to execute a SQL query, one to describe a list of tables in the database, and one to list all of the tables available in the database. \n",
    "\n",
    "We can pass the tool list to our OpenAI agent and test it out:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e0a70d1-3160-42e2-ba56-75577f387175",
   "metadata": {},
   "outputs": [],
   "source": [
    "agent = FunctionAgent(\n",
    "    tools=db_tools.to_tool_list(),\n",
    "    llm=OpenAI(model=\"gpt-4.1\"),\n",
    ")\n",
    "\n",
    "# Context to store chat history\n",
    "from llama_index.core.workflow import Context\n",
    "ctx = Context(agent)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "291184d2-ba13-471c-ad78-2b605bf06e6e",
   "metadata": {},
   "source": [
    "At this point our Agent is fully ready to start making queries to our database:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0ae36c93-ab77-4dd3-9cf0-a6ed7c3c598d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(await agent.run(\"What tables does this database contain\", ctx=ctx))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c77be8af-6e08-45da-b36f-8e90abb91cc6",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(await agent.run(\"Can you describe the messages table\", ctx=ctx))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "54a57d0b-ebea-48e5-978c-90a7846b6504",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(await agent.run(\"Fetch the most recent message and display the body\", ctx=ctx))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
